#include "pch.h"
#include "StrHelper.h"

namespace Str
{

void _AppendFormat(std::string& str, LPCSTR lpFormat, ...)
{
	va_list args;
	va_start(args, lpFormat);
	AppendFormatV(str, lpFormat, args);
	va_end(args);
}

void _AppendFormat(std::wstring& str, LPCWSTR lpFormat, ...)
{
	va_list args;
	va_start(args, lpFormat);
	AppendFormatV(str, lpFormat, args);
	va_end(args);
}

void AppendFormatV(std::string& str, LPCSTR lpFormat, va_list args)
{
	if (!lpFormat)
		return;

	int nSize = _vscprintf(lpFormat, args);
	if (nSize > 0)
	{
		size_t nOldSize = str.size();
		str.resize(nOldSize + nSize);
		vsprintf_s((LPSTR)str.c_str() + nOldSize, nSize + 1, lpFormat, args);
	}
}

void AppendFormatV(std::wstring& str, LPCWSTR lpFormat, va_list args)
{
	if (!lpFormat)
		return;

	int nSize = _vscwprintf(lpFormat, args);
	if (nSize > 0)
	{
		size_t nOldSize = str.size();
		str.resize(nOldSize + nSize);
		vswprintf_s((LPWSTR)str.c_str() + nOldSize, nSize + 1, lpFormat, args);
	}
}

std::string WCharToMByte(LPCWSTR lpSrc, int nLen, UINT nCodePage)
{
	std::string strRet;

	if (!lpSrc || nLen <= 0)
	{
	}
	else if (nLen > 256)
	{
		int nDstLen = WideCharToMultiByte(nCodePage, 0, lpSrc, nLen, NULL, 0, NULL, NULL);
		strRet.resize(nDstLen);
		WideCharToMultiByte(nCodePage, 0, lpSrc, nLen, (LPSTR)strRet.c_str(), nDstLen, NULL, NULL);
	}
	else
	{
		int nDstLen = nLen * (nCodePage == CP_UTF8 ? 3 : 2);
		LPSTR lpDst = (LPSTR)alloca(nDstLen);
		strRet.assign(lpDst, WideCharToMultiByte(nCodePage, 0, lpSrc, nLen, lpDst, nDstLen, NULL, NULL));
	}

	return strRet;
}

std::wstring MByteToWChar(LPCSTR lpSrc, int nLen, UINT nCodePage)
{
	std::wstring strRet;

	if (!lpSrc || nLen <= 0)
	{
	}
	else if (nLen > 256)
	{
		int nDstLen = MultiByteToWideChar(nCodePage, 0, lpSrc, nLen, NULL, 0);
		strRet.resize(nDstLen);
		MultiByteToWideChar(nCodePage, 0, lpSrc, nLen, (LPWSTR)strRet.c_str(), nDstLen);
	}
	else
	{
		LPWSTR lpDst = (LPWSTR)alloca(nLen * sizeof(wchar_t));
		strRet.assign(lpDst, MultiByteToWideChar(nCodePage, 0, lpSrc, nLen, lpDst, nLen));
	}

	return strRet;
}

std::string Unicode2ANSI(const std::wstring_view& str)
{
	return WCharToMByte(str.data(), (int)str.size(), CP_ACP);
}

std::wstring ANSI2Unicode(const std::string_view& str)
{
	return MByteToWChar(str.data(), (int)str.size(), CP_ACP);
}

std::string Unicode2UTF8(const std::wstring_view& str)
{
	return WCharToMByte(str.data(), (int)str.size(), CP_UTF8);
}

std::wstring UTF82Unicode(const std::string_view& str)
{
	return MByteToWChar(str.data(), (int)str.size(), CP_UTF8);
}

std::wstring StringToLower(std::wstring str)
{
	CharLowerBuffW((LPWSTR)str.c_str(), (DWORD)str.size());
	return str;
}

}	// namespace Str
